<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>Hexo</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="第二十二章Request和Response01 Request_原理和继承体系 Request_原理   request对象和response对象的原理   request和response对象是由服务器创建的。我们来使用它们。    request对象是来获取请求消息，response对象是来设置响应消息。         Request_继承体系   request对象和response对象的">
<meta property="og:type" content="article">
<meta property="og:title" content="Hexo">
<meta property="og:url" content="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%8C%E7%AB%A0Request%E5%92%8CResponse/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="第二十二章Request和Response01 Request_原理和继承体系 Request_原理   request对象和response对象的原理   request和response对象是由服务器创建的。我们来使用它们。    request对象是来获取请求消息，response对象是来设置响应消息。         Request_继承体系   request对象和response对象的">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://goofyer.gitee.io/day15/checkCodeServlet">
<meta property="article:published_time" content="2021-12-19T17:35:56.208Z">
<meta property="article:modified_time" content="2021-12-19T17:35:56.209Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://goofyer.gitee.io/day15/checkCodeServlet">
  
    <link rel="alternate" href="/notes-on-computer-expertise/atom.xml" title="Hexo" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/notes-on-computer-expertise/favicon.png">
  
  
    
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/typeface-source-code-pro@0.0.71/index.min.css">

  
  
<link rel="stylesheet" href="/notes-on-computer-expertise/css/style.css">

  
    
<link rel="stylesheet" href="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.css">

  
<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/notes-on-computer-expertise/" id="logo">Hexo</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/">Home</a>
        
          <a class="main-nav-link" href="/notes-on-computer-expertise/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/notes-on-computer-expertise/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://goofyer.gitee.io/notes-on-computer-expertise"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main"><article id="post-Java/第二十二章Request和Response" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%8C%E7%AB%A0Request%E5%92%8CResponse/" class="article-date">
  <time class="dt-published" datetime="2021-12-19T17:35:56.208Z" itemprop="datePublished">2021-12-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h2 id="第二十二章Request和Response"><a href="#第二十二章Request和Response" class="headerlink" title="第二十二章Request和Response"></a>第二十二章Request和Response</h2><h3 id="01-Request-原理和继承体系"><a href="#01-Request-原理和继承体系" class="headerlink" title="01 Request_原理和继承体系"></a>01 Request_原理和继承体系</h3><ul>
<li><p>Request_原理</p>
<ul>
<li><ol>
<li><p>request对象和response对象的原理</p>
<ul>
<li><ol>
<li>request和response对象是由服务器创建的。我们来使用它们。</li>
</ol>
</li>
<li><ol>
<li>request对象是来获取请求消息，response对象是来设置响应消息。</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
<li><p>Request_继承体系</p>
<ul>
<li><ol>
<li><p>request对象和response对象的原理</p>
<ul>
<li><ol>
<li>request和response对象是由服务器创建的。我们来使用它们。</li>
</ol>
</li>
<li><ol>
<li>request对象是来获取请求消息，response对象是来设置响应消息。</li>
</ol>
</li>
<li><p>代码</p>
<ul>
<li>package cn.itcast.web.request;</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>/**</p>
<ul>
<li><p>演示Request对象获取请求行数据<br>*/<br>@WebServlet(“/requestDemo1”)<br>public class RequestDemo1 extends HttpServlet {<br> protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br> }<br> protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {</p>
<pre><code> /*
     1. 获取请求方式 ：GET
         * String getMethod()
     2. (*)获取虚拟目录：/day14
         * String getContextPath()
     3. 获取Servlet路径: /requestDemo1
         * String getServletPath()
     4. 获取get方式请求参数：name=zhangsan
         * String getQueryString()
     5. (*)获取请求URI：/day14/demo1
         * String getRequestURI():        /day14/requestDemo1
         * StringBuffer getRequestURL()  :http://localhost/day14/requestDemo1
     6. 获取协议及版本：HTTP/1.1
         * String getProtocol()
     7. 获取客户机的IP地址：
         * String getRemoteAddr()
  */
 //1. 获取请求方式 ：GET
 String method = request.getMethod();
 System.out.println(method);
 //2.(*)获取虚拟目录：/day14
 String contextPath = request.getContextPath();
 System.out.println(contextPath);
 //3. 获取Servlet路径: /demo1
 String servletPath = request.getServletPath();
 System.out.println(servletPath);
 //4. 获取get方式请求参数：name=zhangsan
 String queryString = request.getQueryString();
 System.out.println(queryString);
 //5.(*)获取请求URI：/day14/demo1
 String requestURI = request.getRequestURI();
 StringBuffer requestURL = request.getRequestURL();
 System.out.println(requestURI);
 System.out.println(requestURL);
 //6. 获取协议及版本：HTTP/1.1
 String protocol = request.getProtocol();
 System.out.println(protocol);
 //7. 获取客户机的IP地址：
 String remoteAddr = request.getRemoteAddr();
 System.out.println(remoteAddr);
</code></pre><p> }</p>
<ul>
<li><ol>
<li><p>request对象继承体系结构：    </p>
<ul>
<li>ServletRequest         —    接口<br>|    继承<br>HttpServletRequest  — 接口<br>|    实现<br>org.apache.catalina.connector.RequestFacade 类(tomcat)</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>request功能：</p>
<ul>
<li><ol>
<li><p>获取请求消息数据</p>
<ul>
<li><ol>
<li>获取请求行数据</li>
</ol>
<ul>
<li><ul>
<li>GET /day14/demo1?name=zhangsan HTTP/1.1</li>
</ul>
</li>
<li><ul>
<li><p>方法：</p>
<ul>
<li><ol>
<li><p>获取请求方式 ：GET</p>
<ul>
<li><ul>
<li>String getMethod()  </li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>(*)获取虚拟目录：/day14</p>
<ul>
<li><ul>
<li>String getContextPath()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取Servlet路径: /demo1</p>
<ul>
<li><ul>
<li>String getServletPath()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取get方式请求参数：name=zhangsan</p>
<ul>
<li><ul>
<li>String getQueryString()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>(*)获取请求URI：/day14/demo1</p>
<ul>
<li><ul>
<li>String getRequestURI()：           /day14/demo1</li>
</ul>
</li>
<li><ul>
<li>StringBuffer getRequestURL()：<a target="_blank" rel="noopener" href="http://localhost/day14/demo1">http://localhost/day14/demo1</a></li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取协议及版本：HTTP/1.1</p>
<ul>
<li><ul>
<li>String getProtocol()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取客户机的IP地址：</p>
<ul>
<li><ul>
<li>String getRemoteAddr()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ol>
<li>获取请求头数据</li>
</ol>
<ul>
<li><ul>
<li><p>方法：</p>
<ul>
<li><ul>
<li>(*)String getHeader(String name)：通过请求头的名称获取请求头的值</li>
</ul>
</li>
<li><ul>
<li>Enumeration<String> getHeaderNames()：获取所有的请求头名称</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>package cn.itcast.web.request;</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;<br>import java.util.Enumeration;</p>
<p>@WebServlet(“/requestDemo2”)<br>public class RequestDemo2 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //演示获取请求头数据<br>        //1.获取所有请求头名称<br>        Enumeration<String> headerNames = request.getHeaderNames();<br>        //2.遍历<br>        while (headerNames.hasMoreElements()) {<br>            String name = headerNames.nextElement();<br>            //根据名称获取请求头的值<br>            String value = request.getHeader(name);<br>            System.out.println(name + “—-“ + value);<br>        }<br>    }<br>}</p>
<p>package cn.itcast.web.request;</p>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;<br>import java.util.Enumeration;</p>
<p>@WebServlet(“/requestDemo3”)<br>public class RequestDemo3 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //演示获取请求头数据：user-agent 告诉服务器客户端的版本是什么—&gt;判断浏览器版本<br>        String agent = request.getHeader(“user-agent”); // user-agent不区分大小写<br>        //判断agent的浏览器版本<br>        if (agent.contains(“Chrome”)) {<br>            //谷歌<br>            System.out.println(“谷歌来了…”);<br>        } else if (agent.contains(“Firefox”)) {<br>            //火狐<br>            System.out.println(“火狐来了…”);<br>        }<br>    }<br>}<br>演示获取请求头数据、防盗链</p>
<pre><code>            - 
</code></pre><p>package cn.itcast.web.request;</p>
<p>import javax.servlet.ServletContext;<br>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>@WebServlet(“/requestDemo4”)<br>public class RequestDemo4 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }</p>
<pre><code>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
    //演示获取请求头数据:referer
    String referer = request.getHeader(&quot;referer&quot;);
    System.out.println(referer);//http://localhost/day14/login.html
    //防盗链
    if (referer != null) &#123;
        if (referer.contains(&quot;/day14&quot;)) &#123;
            //正常访问
</code></pre><p>//                 System.out.println(“播放电影….”);<br>                response.setContentType(“text/html;charset=utf-8”);<br>                response.getWriter().write(“播放电影….”);<br>            } else {<br>                //盗链<br>//                System.out.println(“想看电影吗？来优酷吧…”);<br>                response.setContentType(“text/html;charset=utf-8”);<br>                response.getWriter().write(“想看电影吗？来优酷吧…”);<br>            }<br>        }<br>    }<br>}</p>
<pre><code>        - 3. 获取请求体数据

            - 获取所有请求头名称

                - * 请求体：只有POST请求方式，才有请求体，在请求体中封装了POST请求的请求参数
                - * 步骤：
                - 1. 获取流对象

                    - *  BufferedReader getReader()：获取字符输入流，只能操作字符数据
                    - *  ServletInputStream getInputStream()：获取字节输入流，可以操作所有类型数据
                    - * 在文件上传知识点后讲解

                - 2. 再从流对象中拿数据

                    -  
</code></pre><p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.BufferedReader;<br>import java.io.IOException;</p>
<p>@WebServlet(“/requestDemo5”)<br>public class RequestDemo5 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //获取请求消息体—请求参数<br>        //1.获取字符流<br>        BufferedReader br = request.getReader();<br>        //2.读取数据<br>        String line = null;<br>        while ((line = br.readLine()) != null) {<br>            System.out.println(line);<br>        }<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>    }<br>}</p>
<pre><code>    - 2. 其他功能：

        - 1. 获取请求参数通用方式：不论get还是post请求方式都可以使用下列方法来获取请求参数。

            - 1. String getParameter(String name)：根据参数名称获取参数值 username=zs&amp;password=123
            - 2. String[] getParameterValues(String name)：根据参数名称获取参数值的数组 hobby=xx&amp;hobby=game
            - 3. Enumeration&lt;String&gt; getParameterNames()：获取所有请求的参数名称
            - 4. Map&lt;String,String[]&gt; getParameterMap()：获取所有参数的map集合
            - @WebServlet(&quot;/requestDemo6&quot;)
</code></pre><p>public class RequestDemo6 extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //post 获取请求参数</p>
<pre><code>    //根据参数名称获取参数值
    /* String username = request.getParameter(&quot;username&quot;);
    System.out.println(&quot;post&quot;);
    System.out.println(username);*/

    //根据参数名称获取参数值的数组
    String[] hobbies = request.getParameterValues(&quot;hobby&quot;);
    /*for (String hobby : hobbies) &#123;
        System.out.println(hobby);
    &#125;*/

    //获取所有请求的参数名称
    /*Enumeration&lt;String&gt; parameterNames = request.getParameterNames();
    while(parameterNames.hasMoreElements())&#123;
        String name = parameterNames.nextElement();
        System.out.println(name);
        String value = request.getParameter(name);
        System.out.println(value);
        System.out.println(&quot;----------------&quot;);
    &#125;*/

    // 获取所有参数的map集合
    Map&lt;String, String[]&gt; parameterMap = request.getParameterMap();
    //遍历
    Set&lt;String&gt; keyset = parameterMap.keySet();
    for (String name : keyset) &#123;
        //获取键 获取值
        String[] values = parameterMap.get(name);
        System.out.println(name);
        for (String value : values) &#123;
            System.out.println(value);
        &#125;
        System.out.println(&quot;-----------------&quot;);
    &#125;
&#125;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
    //get 获取请求参数
   /* //根据参数名称获取参数值
    String username = request.getParameter(&quot;username&quot;);
    System.out.println(&quot;get&quot;);
    System.out.println(username);*/
    this.doPost(request, response);
&#125;
</code></pre><p>}</p>
<pre><code>            - 中文乱码问题：

                -     * get方式：tomcat 8 已经将get方式乱码问题解决了。
                -     * post方式：会乱码
                -         * 解决：在获取参数前，设置request的编码 request.setCharacterEncoding(&quot;utf-8&quot;) ;
                - get方法（tomcat 8 已经将get方式乱码问题解决）
                - post方式（设置request的编码）

        - 2. 请求转发

            - 1. 步骤：

                - 1. 通过request对象获取请求转发器对象：RequestDispatcher getRequestDispatcher(String path)
                - 2. 使用RequestDispatcher对象来进行转发：forward(ServletRequest request, ServletResponse response)

            - 2. 特点：

                - 1. 浏览器地址栏路径不发生变化。
                - 2. 只能转发到当前服务器内部资源中。
                - 3. 转发是一次请求。

        - 3. 共享数据

            - * 域对象：一个有作用范围的对象，可以在范围内共享数据
            - * request域：代表一次请求的范围，一般用于请求转发的多个资源中共享数据
            - * 方法：

                - 1. void setAttribute(String name,Object obj)：存储数据
                - 2. Object getAttitude(String name)：通过键获取值
                - 3. void removeAttribute(String name)：通过键移除键值对

        - 4. 获取ServletContext

            - * ServletContext getServletContext()
</code></pre><h3 id="05-request登录案例"><a href="#05-request登录案例" class="headerlink" title="05 request登录案例"></a>05 request登录案例</h3><ul>
<li><ul>
<li><p>用户登录案例需求：</p>
<ul>
<li><p>1.编写login.html登录页面</p>
<ul>
<li>username &amp; password 两个输入框</li>
</ul>
</li>
<li><p>2.使用Druid数据库连接池技术,操作mysql，day14数据库中user表</p>
</li>
<li>3.使用JdbcTemplate技术封装JDBC</li>
<li>4.登录成功跳转到SuccessServlet展示：登录成功！用户名,欢迎您</li>
<li>5.登录失败跳转到FailServlet展示：登录失败，用户名或密码错误</li>
</ul>
</li>
</ul>
</li>
<li><p>开发步骤</p>
<ul>
<li><p>1：创建项目，导入html页面，配置文件，jar包</p>
<ul>
<li>子主题 1</li>
</ul>
</li>
<li><p>开发步骤2：创建数据库环境</p>
<ul>
<li>CREATE DATABASE day14;</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>USE day14;</p>
<p>CREATE TABLE USER(<br>    id INT PRIMARY KEY AUTO_INCREMENT,<br>    username VARCHAR(32) UNIQUE NOT NULL,<br>    PASSWORD VARCHAR(32) NOT NULL<br>);</p>
<pre><code>- 开发步骤4：创建包cn.itcast.util，编写工具类JDBCUtils

    - package cn.itcast.util;
</code></pre><p>import com.alibaba.druid.pool.DruidDataSourceFactory;</p>
<p>import javax.sql.DataSource;<br>import javax.xml.crypto.Data;<br>import java.io.IOException;<br>import java.io.InputStream;<br>import java.sql.Connection;<br>import java.sql.SQLException;<br>import java.util.Properties;</p>
<p>/**</p>
<ul>
<li><p>JDBC工具类 使用Durid连接池<br>*/<br>public class JDBCUtils {<br> private static DataSource ds;<br> static {</p>
<pre><code> try &#123;
     //1.加载配置文件
     Properties pro = new Properties();
     //使用ClassLoader加载配置文件，获取字节输入流
     InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream(&quot;druid.properties&quot;);
     pro.load(is);
     //2.初始化连接池对象
     ds = DruidDataSourceFactory.createDataSource(pro);
 &#125; catch (IOException e) &#123;
     e.printStackTrace();
 &#125; catch (Exception e) &#123;
     e.printStackTrace();
 &#125;
</code></pre><p> }</p>
<p> /**</p>
<ul>
<li><p>获取连接池对象<br>*/<br>public static DataSource getDataSource() {<br> return ds;<br>}</p>
<p>/**</p>
</li>
<li><p>获取连接Connection对象<br>*/<br>public static Connection getConnection() throws SQLException {<br> return ds.getConnection();<br>}</p>
<ul>
<li><p>开发步骤5：创建包cn.itcast.dao，创建类UserDao，提供login方法</p>
<ul>
<li>// 调用query方法<br>User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), loginUser.getUsername(), loginUser.getPassword());<br>————————————————</li>
<li>/**</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>操作数据库中User表的类——增删改查方法全在此类中<br><em>/<br>public class UserDao {<br> //声明JDBCTemplate对象共用<br> private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());<br> /*</em></p>
<ul>
<li>登录方法<br>*</li>
<li>@param loginUser 只有用户名和密码</li>
<li><p>@return user包含用户全部数据, 没有查询到，返回null<br>*/<br>public User login(User loginUser) {<br> try {</p>
<pre><code> //1.编写sql
 String sql = &quot;select * from user where username = ? and password = ?&quot;;
 //2.调用query方法
 User user = template.queryForObject(sql,
         new BeanPropertyRowMapper&lt;User&gt;(User.class),
         loginUser.getUsername(), loginUser.getPassword());
 return user;
</code></pre><p> } catch (DataAccessException e) {</p>
<pre><code> e.printStackTrace(); // 记录日志
 return null;
</code></pre><p> }<br>}<br>}<br>测试login()方法</p>
<ul>
<li><p>​开发步骤6： 编写cn.itcast.web.servlet.LoginServlet类</p>
<ul>
<li>@WebServlet(“/loginServlet”)<br>public class LoginServlet extends HttpServlet {<br>@Override<br>protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br>//1.设置编码<br>req.setCharacterEncoding(“utf-8”);<br>/<em> //2.获取请求参数<br>String username = req.getParameter(“username”);<br>String password = req.getParameter(“password”);<br>//3.封装user对象<br>User loginUser = new User();<br>loginUser.setUsername(username);<br>loginUser.setPassword(password);</em>/<br>//2.获取所有请求参数<br>Map<String, String[]> map = req.getParameterMap();<br>//3.创建User对象<br>User loginUser = new User();<br>//3.2使用BeanUtils封装<br>try {<br> BeanUtils.populate(loginUser, map);<br>} catch (IllegalAccessException e) {<br> e.printStackTrace();<br>} catch (InvocationTargetException e) {<br> e.printStackTrace();<br>}</li>
</ul>
<p>//4.调用UserDao的login方法<br>UserDao dao = new UserDao();<br>User user = dao.login(loginUser);</p>
<p>//5.判断user<br>if (user == null) {<br>   //登录失败<br>   req.getRequestDispatcher(“/failServlet”).forward(req, resp);<br>} else {<br>   //登录成功<br>   //存储数据<br>   req.setAttribute(“user”, user);<br>   //转发<br>   req.getRequestDispatcher(“/successServlet”).forward(req, resp);<br>}<br>}</p>
</li>
</ul>
<p>@Override<br>protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {<br> this.doGet(req, resp);<br>}<br>}</p>
<ul>
<li><p>​开发步骤7：编写FailServlet和SuccessServlet类</p>
<ul>
<li>@WebServlet(“/successServlet”)<br>public class SuccessServlet extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>//获取request域中共享的user对象<br>User user = (User) request.getAttribute(“user”);<br>if(user != null){<br> //给页面写一句话<br> //设置编码<br> response.setContentType(“text/html;charset=utf-8”);<br> //输出<br> response.getWriter().write(“登录成功！”+user.getUsername()+”,欢迎您！”);<br>}<br>}<br>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>this.doPost(request,response);<br>}<br>}<br>FailServlet.java：</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>package cn.itcast.web.servlet;</p>
<p>import javax.servlet.ServletException;<br>import javax.servlet.annotation.WebServlet;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;<br>import java.io.IOException;</p>
<p>@WebServlet(“/failServlet”)<br>public class FailServlet extends HttpServlet {<br>    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        //给页面写一句话<br>        //设置编码<br>        response.setContentType(“text/html;charset=utf-8”);<br>        //输出<br>        response.getWriter().write(“登录失败，用户名或密码错误！”);<br>    }<br>    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>        this.doPost(request,response);<br>    }<br>}</p>
<pre><code>- 开发步骤8：login.html中form表单的action路径的写法
- 开发步骤9：BeanUtils工具类，简化数据封装

    - 子主题 9
    - 子主题 10
    - 子主题 11
    - 子主题 12
</code></pre><ul>
<li><p>登录案例_BeanUtils介绍</p>
<ul>
<li><ul>
<li><p>用于封装JavaBean的</p>
<ul>
<li><ol>
<li><p>JavaBean：标准的Java类</p>
<ul>
<li><ol>
<li><p>要求：</p>
<ul>
<li><ol>
<li>类必须被public修饰</li>
</ol>
</li>
<li><ol>
<li>必须提供空参的构造器</li>
</ol>
</li>
<li><ol>
<li>成员变量必须使用private修饰</li>
</ol>
</li>
<li><ol>
<li>提供公共setter和getter方法</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>功能：封装数据</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>概念：</p>
<ul>
<li><p>成员变量：</p>
<ul>
<li>属性：setter和getter方法截取后的产物</li>
</ul>
</li>
<li><p>例如：getUsername() —&gt; Username—&gt; username</p>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>方法：</p>
<ul>
<li><ol>
<li>setProperty()</li>
</ol>
</li>
<li><ol>
<li>getProperty()</li>
</ol>
</li>
<li><ol>
<li>populate(Object obj, Map map):将map集合的键值对信息，封装到对应的JavaBean对象中</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="06-HTTP响应协议"><a href="#06-HTTP响应协议" class="headerlink" title="06 HTTP响应协议"></a>06 HTTP响应协议</h3><ul>
<li><ol>
<li><p>请求消息：客户端发送给服务器端的数据。</p>
<ul>
<li><ul>
<li><p>数据格式：</p>
<ul>
<li><ol>
<li>请求行</li>
</ol>
</li>
<li><ol>
<li>请求头</li>
</ol>
</li>
<li><ol>
<li>请求空行</li>
</ol>
</li>
<li><ol>
<li>请求体</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>响应消息：服务器端发送给客户端的数据。</p>
<ul>
<li><ul>
<li><p>数据格式：</p>
<ul>
<li><ol>
<li>响应行</li>
</ol>
</li>
<li><ol>
<li>响应头</li>
</ol>
</li>
<li><ol>
<li>响应空行</li>
</ol>
</li>
<li><ol>
<li>响应体</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>响应字符串格式</p>
<ul>
<li>HTTP/1.1 200 OK<br>Content-Type: text/html;charset=UTF-8<br>Content-Length: 101<br>Date: Wed, 06 Jun 2018 07:08:42 GMT</li>
</ul>
<html>
 <head>
   <title>$Title$</title>
 </head>
 <body>
 hello , response
 </body>
</html>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><p>响应消息：服务器端发送给客户端的数据。</p>
<ul>
<li><ul>
<li><p>数据格式：</p>
<ul>
<li><ol>
<li><p>响应行</p>
<ul>
<li><ol>
<li>组成：协议/版本 响应状态码 状态码描述</li>
</ol>
</li>
<li><ol>
<li><p>响应状态码：服务器告诉客户端浏览器本次请求和响应的一个状态。</p>
<ul>
<li><ol>
<li>状态码都是3位数字 </li>
</ol>
</li>
<li><ol>
<li>分类：</li>
</ol>
<ul>
<li><ol>
<li>1xx：服务器就收客户端消息，但没有接受完成，等待一段时间后，发送1xx多状态码</li>
</ol>
</li>
<li><ol>
<li>2xx：成功。代表：200</li>
</ol>
</li>
<li><ol>
<li>3xx：重定向。代表：302(重定向)，304(访问缓存)</li>
</ol>
</li>
<li><ol>
<li><p>4xx：客户端错误。</p>
<ul>
<li><ul>
<li><p>代表：</p>
<ul>
<li><ul>
<li>404：请求路径没有对应的资源</li>
</ul>
</li>
<li><ul>
<li>405：请求方式没有对应的doXxx方法</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>5xx：服务器端错误。代表：500(服务器内部出现异常)</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>响应头：</p>
<ul>
<li><ol>
<li>格式：头名称： 值</li>
</ol>
</li>
<li><ol>
<li><p>常见的响应头：</p>
<ul>
<li><ol>
<li>Content-Type：服务器告诉客户端本次响应体数据格式以及编码格式。</li>
</ol>
</li>
<li><ol>
<li><p>Content-disposition：服务器告诉客户端以什么格式打开响应体数据。</p>
<ul>
<li><ul>
<li>值：</li>
</ul>
<ul>
<li><ul>
<li>in-line：默认值，在当前页面内打开</li>
</ul>
</li>
<li><ul>
<li>attachment;filename=xxx：以附件形式打开响应体。（应用：文件下载）</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<h3 id="07-response之重定向"><a href="#07-response之重定向" class="headerlink" title="07 response之重定向"></a>07 response之重定向</h3><ul>
<li><ul>
<li><p>Response对象 功能：设置响应消息。</p>
<ul>
<li><ol>
<li><p>设置响应行</p>
<ul>
<li><ol>
<li>格式：HTTP/1.1 200 ok</li>
</ol>
</li>
<li><ol>
<li>设置状态码：setStatus(int sc) </li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>设置响应头：setHeader(String name, String value) </li>
</ol>
</li>
<li><ol>
<li><p>设置响应体：</p>
<ul>
<li><ul>
<li><p>使用步骤：</p>
<ul>
<li><ol>
<li><p>获取输出流</p>
<ul>
<li><ul>
<li>字符输出流：PrintWriter getWriter()</li>
</ul>
</li>
<li><ul>
<li>字节输出流：ServletOutputStream getOutputStream()</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>使用输出流，将数据输出到客户端浏览器</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>案例：</p>
<ul>
<li><ol>
<li><p>完成重定向</p>
<ul>
<li><ul>
<li>重定向：资源跳转的方式</li>
</ul>
</li>
<li><ul>
<li><p>代码实现：</p>
<ul>
<li>//1. 设置状态码为302<br>response.setStatus(302);<br>//2.设置响应头location<br>response.setHeader(“location”,”/day15/responseDemo2”);</li>
</ul>
<p>//简单的重定向方法<br>response.sendRedirect(“/day15/responseDemo2”)</p>
</li>
</ul>
</li>
<li><ul>
<li><p>重定向的特点：redirect</p>
<ul>
<li><ol>
<li>地址栏发生变化</li>
</ol>
</li>
<li><ol>
<li>重定向可以访问其他站点(服务器)的资源</li>
</ol>
</li>
<li><ol>
<li>重定向是两次请求，不能使用request对象来共享数据。</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>转发的特点：forward</p>
<ul>
<li><ol>
<li>转发地址栏路径不变</li>
</ol>
</li>
<li><ol>
<li>转发只能访问当前服务器下的资源</li>
</ol>
</li>
<li><ol>
<li>转发是一次请求，可以使用request对象来共享数据。</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>forward(转发)和redirect(重定向)区别</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>服务器输出字符数据到浏览器</li>
</ol>
</li>
<li><ol>
<li>服务器输出字节数据到浏览器</li>
</ol>
</li>
<li><ol>
<li>验证码</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="08-response之相对路径和绝对路径"><a href="#08-response之相对路径和绝对路径" class="headerlink" title="08 response之相对路径和绝对路径"></a>08 response之相对路径和绝对路径</h3><ul>
<li><ol>
<li><p>完成重定向    </p>
<ul>
<li><ul>
<li><p>路径写法：</p>
<ul>
<li><ol>
<li><p>路径分类</p>
<ul>
<li><ol>
<li>相对路径：通过相对路径不可以确定唯一资源。</li>
</ol>
<ul>
<li><ul>
<li>如：./index.html</li>
</ul>
</li>
<li><ul>
<li>不以/开头，以.开头路径</li>
</ul>
</li>
<li><ul>
<li><p>规则：找到当前资源和目标资源之间的相对位置关系。</p>
<ul>
<li><ul>
<li>./：当前目录</li>
</ul>
</li>
<li><ul>
<li>../:后退一级目录</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><ol>
<li>绝对路径：通过绝对路径可以确定唯一资源。</li>
</ol>
<ul>
<li><ul>
<li>如：<a target="_blank" rel="noopener" href="http://localhost/day15/responseDemo2">http://localhost/day15/responseDemo2</a> ； 省略协议、域名、端口：/day15/responseDemo2</li>
</ul>
</li>
<li><ul>
<li>以/开头的路径</li>
</ul>
</li>
<li><ul>
<li>给客户端浏览器使用：需要加虚拟目录(项目的访问路径)。</li>
</ul>
</li>
<li><ul>
<li>建议虚拟目录动态获取：request.getContextPath()</li>
</ul>
</li>
<li><ul>
<li><a>、<form>、重定向 …</li>
</ul>
</li>
<li><ul>
<li>给服务器使用：不需要加虚拟目录。</li>
</ul>
</li>
<li><ul>
<li>转发路径</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="09-response之输出数据"><a href="#09-response之输出数据" class="headerlink" title="09 response之输出数据"></a>09 response之输出数据</h3><ul>
<li><ul>
<li><p>案例：</p>
<ul>
<li><ol>
<li>完成重定向</li>
</ol>
</li>
<li><ol>
<li><p>服务器输出字符数据到浏览器</p>
<ul>
<li><ul>
<li><p>步骤：</p>
<ul>
<li><ol>
<li>获取字符输出流（流向客户端浏览器）</li>
</ol>
</li>
<li><ol>
<li><p>输出数据</p>
<ul>
<li><ul>
<li>注意：</li>
</ul>
<ul>
<li><ul>
<li><p>乱码问题：</p>
<ul>
<li><ol>
<li>PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1</li>
</ol>
</li>
<li><ol>
<li>设置该流的默认编码</li>
</ol>
</li>
<li><ol>
<li><p>告诉浏览器响应体使用的编码</p>
<ul>
<li>//简单的形式，设置编码，是在获取流之前设置<br>response.setContentType(“text/html;charset=utf-8”);</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><p>@WebServlet(“/responseDemo4”)<br>public class ResponseDemo4 extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>  //获取流对象之前，设置流的默认编码：ISO-8859-1 设置为：GBK<br>  //response.setCharacterEncoding(“utf-8”);<br>  //告诉浏览器，服务器发送的消息体数据的编码。建议浏览器使用该编码解码<br>  //response.setHeader(“content-type”,”text/html;charset=utf-8”);</p>
<p>  //简单的形式，设置编码<br>  response.setContentType(“text/html;charset=utf-8”);</p>
<p>  //1.获取字符输出流<br>  PrintWriter pw = response.getWriter();<br>  //2.输出数据<br>  //pw.write(“<h1>hello response</h1>“);<br>  pw.write(“你好啊啊啊 response”);<br>}</p>
</li>
</ul>
<p>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {</p>
<pre><code>this.doPost(request, response);
</code></pre><p>}<br>}</p>
<ul>
<li><ol>
<li><p>服务器输出字节数据到浏览器</p>
<ul>
<li><ul>
<li><p>步骤：</p>
<ul>
<li><ol>
<li>获取字节输出流</li>
</ol>
</li>
<li><ol>
<li>输出数据</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li>验证码</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="10-response之验证码"><a href="#10-response之验证码" class="headerlink" title="10 response之验证码"></a>10 response之验证码</h3><ul>
<li><p>Response 对象 </p>
<ul>
<li><ul>
<li><p>案例：</p>
<ul>
<li><ol>
<li>完成重定向</li>
</ol>
</li>
<li><ol>
<li>服务器输出字符数据到浏览器</li>
</ol>
</li>
<li><ol>
<li>服务器输出字节数据到浏览器</li>
</ol>
</li>
<li><ol>
<li><p>验证码</p>
<ul>
<li><ol>
<li>本质：图片</li>
</ol>
</li>
<li><ol>
<li>目的：防止恶意表单注册</li>
</ol>
</li>
<li><p>代码</p>
<ul>
<li>@WebServlet(“/checkCodeServlet”)<br>public class CheckCodeServlet extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>int width = 100;<br>int height = 50;<br>//1.创建一对象，在内存中图片(验证码图片对象)<br>BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<p>//2.美化图片<br>//2.1 填充背景色<br>Graphics g = image.getGraphics();//画笔对象<br>g.setColor(Color.PINK);//设置画笔颜色<br>g.fillRect(0, 0, width, height); // 从(0,0)开始填充</p>
<p>//2.2画边框<br>g.setColor(Color.BLUE);<br>g.drawRect(0, 0, width - 1, height - 1);</p>
<p>String str = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789”;<br>//生成随机角标<br>Random ran = new Random();<br>for (int i = 1; i &lt;= 4; i++) {</p>
<pre><code>int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
//2.3写验证码
g.drawString(ch + &quot;&quot;, width / 5 * i, height / 2);
</code></pre><p>}</p>
<p>//2.4画干扰线<br>g.setColor(Color.GREEN);<br>//随机生成坐标点<br>for (int i = 0; i &lt; 10; i++) {</p>
<pre><code>int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1, y1, x2, y2);
</code></pre><p>}</p>
<p>//3.将图片输出到页面展示<br>ImageIO.write(image, “jpg”, response.getOutputStream());<br>}</p>
</li>
</ul>
<p>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>  this.doPost(request, response);<br>}<br>}</p>
</li>
<li><p>Response_案例4_验证码_点击</p>
<ul>
<li><p>分析：</p>
<ul>
<li><p>点击超链接或者图片，需要换一张</p>
<ul>
<li>1.给超链接和图片绑定单击事件</li>
<li>2.重新设置图片的src属性值</li>
</ul>
</li>
</ul>
</li>
<li><p>代码</p>
<ul>
<li>&lt;!DOCTYPE html&gt;<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码图片</title>
<script>
window.onload = function () {
//1.获取图片对象
var img = document.getElementById("checkCode");
//2.绑定单击事件
img.onclick = function () {
  //加时间戳
  var date = new Date().getTime();
  img.src = "/day15/checkCodeServlet?" + date;
}
}
</script>
</head>
<body>
<img id="checkCode" src="/day15/checkCodeServlet"/>
<a id="change" href="">看不清？换一张！</a>
</body>
</html>

</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="11-ServletContext对象"><a href="#11-ServletContext对象" class="headerlink" title="11 ServletContext对象"></a>11 ServletContext对象</h3><ul>
<li><ol>
<li>概念：代表整个web应用，可以和程序的容器(服务器)来通信。</li>
</ol>
</li>
<li><ol>
<li><p>获取</p>
<ul>
<li><ol>
<li><p>通过request对象获取</p>
<ul>
<li>request.getServletContext();</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>通过HttpServlet获取</p>
<ul>
<li>this.getServletContext();</li>
</ul>
</li>
</ol>
</li>
<li><p>代码</p>
<ul>
<li>@WebServlet(“/servletContextDemo1”)<br>public class ServletContextDemo1 extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>/*<br>  ServletContext对象获取：<pre><code>  1. 通过request对象获取
      request.getServletContext();
  2. 通过HttpServlet获取
      this.getServletContext();
</code></pre>*/<br>//1. 通过request对象获取<br>ServletContext context1 = request.getServletContext();<br>//2. 通过HttpServlet获取<br>ServletContext context2 = this.getServletContext();<br>System.out.println(context1);<br>System.out.println(context2);<br>System.out.println(context1 == context2);//true<br>}<br>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>this.doPost(request, response);<br>}<br>}</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>功能：</p>
<ul>
<li><ol>
<li><p>获取MIME类型：</p>
<ul>
<li><ul>
<li>MIME类型：在互联网通信过程中定义的一种文件数据类型。</li>
</ul>
<ul>
<li><ul>
<li>格式：大类型/小类型，text/html、image/jpeg</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li>获取：String getMimeType(String file)</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>域对象：共享数据。</p>
<ul>
<li><ol>
<li>setAttribute(String name,Object value)</li>
</ol>
</li>
<li><ol>
<li>getAttribute(String name)</li>
</ol>
</li>
<li><ol>
<li>removeAttribute(String name)</li>
</ol>
<ul>
<li><ul>
<li>ServletContext对象范围：所有用户、所有请求的数据。</li>
</ul>
</li>
</ul>
</li>
<li><p>子主题 4</p>
<ul>
<li>子主题 1</li>
<li>子主题 2</li>
<li>子主题 3</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
<li><ol>
<li><p>获取文件的真实(服务器)路径</p>
<ul>
<li><ol>
<li>方法：</li>
</ol>
<ul>
<li>String getRealPath(String path)  </li>
<li>String b = context.getRealPath(“/b.txt”);//web目录下资源访问</li>
<li>System.out.println(b);</li>
<li>String c = context.getRealPath(“/WEB-INF/c.txt”);//WEB-INF目录下的资源访问</li>
<li>System.out.println(c);</li>
<li>String a = context.getRealPath(“/WEB-INF/classes/a.txt”);//src目录下的资源访问</li>
<li>System.out.println(a);</li>
</ul>
</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ol>
</li>
</ul>
<h3 id="12-文件下载"><a href="#12-文件下载" class="headerlink" title="12 文件下载"></a>12 文件下载</h3><ul>
<li><ul>
<li><p>文件下载需求：</p>
<ul>
<li>页面显示超链接</li>
<li>点击超链接后弹出下载提示框</li>
<li>完成图片文件下载</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>分析：</p>
<ul>
<li>超链接指向的资源如果能够被浏览器解析，则在浏览器中展示；如果不能解析，则弹出下载提示框。</li>
<li>任何资源都必须弹出下载提示框。</li>
<li>使用响应头设置资源的打开方式：content-disposition:attachment;filename=xxx</li>
</ul>
</li>
</ul>
</li>
<li><ul>
<li><p>步骤：</p>
<ul>
<li>定义页面，编辑超链接href属性，指向Servlet，传递资源名称filename。</li>
<li>定义Servlet</li>
<li>获取文件名称</li>
<li>使用字节输入流加载文件进内存</li>
<li>指定response的响应头：content-disposition:attachment;filename=xxx</li>
<li>将数据写出到response输出流</li>
</ul>
</li>
</ul>
</li>
<li><p>文件下载_代码实现</p>
<ul>
<li><p>download.html</p>
<ul>
<li>&lt;!DOCTYPE html&gt;<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<a href="/day15/img/1.jpg">图片1</a>
<a href="/day15/img/1.avi">视频</a>
<hr>
<a href="/day15/downloadServlet?filename=九尾.jpg">图片1</a>
<a href="/day15/downloadServlet?filename=1.avi">视频</a>
</body>
</html>
</li>
</ul>
</li>
<li><p>DownloadServlet.java</p>
<ul>
<li><p>@WebServlet(“/downloadServlet”)<br>public class DownloadServlet extends HttpServlet {<br>protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>//1.获取请求参数，文件名称<br>String filename = request.getParameter(“filename”);<br>//2.使用字节输入流加载文件进内存<br>//2.1找到文件服务器路径<br>ServletContext servletContext = this.getServletContext();<br>String realPath = servletContext.getRealPath(“/img/“ + filename);<br>//2.2用字节流关联<br>FileInputStream fis = new FileInputStream(realPath);</p>
<p>//3.设置response的响应头<br>//3.1设置响应头类型：content-type<br>String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型<br>response.setHeader(“content-type”, mimeType);<br>//3.2设置响应头打开方式:content-disposition</p>
<p>//解决中文文件名问题<br>//1.获取user-agent请求头、<br>String agent = request.getHeader(“user-agent”);<br>//2.使用工具类方法编码文件名即可<br>filename = DownLoadUtils.getFileName(agent, filename);</p>
<p>response.setHeader(“content-disposition”, “attachment;filename=” + filename);<br>//4.将输入流的数据写出到输出流中<br>ServletOutputStream sos = response.getOutputStream();<br>byte[] buff = new byte[1024 * 8];<br>int len = 0;<br>while ((len = fis.read(buff)) != -1) {<br>  sos.write(buff, 0, len);<br>}<br>fis.close();<br>}</p>
</li>
</ul>
<p>protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br>  this.doPost(request, response);<br>}<br>}</p>
</li>
</ul>
</li>
<li><ul>
<li><p>中文文件问题</p>
<ul>
<li><ul>
<li><p>解决思路：</p>
<ul>
<li><ol>
<li>获取客户端使用的浏览器版本信息</li>
</ol>
</li>
<li><ol>
<li>根据不同的版本信息，设置filename的编码方式不同</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
<li><p>代码</p>
<ul>
<li><p>DownLoadUtils.java</p>
<ul>
<li>public class DownLoadUtils {<br>public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {<br>if (agent.contains(“MSIE”)) {<br>// IE浏览器<br>filename = URLEncoder.encode(filename, “utf-8”);<br>filename = filename.replace(“+”, “ “);<br>} else if (agent.contains(“Firefox”)) {<br>// 火狐浏览器<br>BASE64Encoder base64Encoder = new BASE64Encoder();<br>filename = “=?utf-8?B?” + base64Encoder.encode(filename.getBytes(“utf-8”)) + “?=”;<br>} else {<br>// 其它浏览器<br>filename = URLEncoder.encode(filename, “utf-8”);<br>}<br>return filename;<br>}</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://goofyer.gitee.io/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%BA%8C%E7%AB%A0Request%E5%92%8CResponse/" data-id="cl403sxr6001hf8vufv4x8cm0" data-title="" class="article-share-link">Share</a>
      
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%89%E7%AB%A0JSP%E3%80%81EL%E5%92%8CJSTL/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          (no title)
        
      </div>
    </a>
  
  
    <a href="/notes-on-computer-expertise/2021/12/20/Java/%E7%AC%AC%E4%BA%8C%E5%8D%81%E4%B8%80%E7%AB%A0Servlet%E5%92%8CHTTP%E8%AF%B7%E6%B1%82%E5%8D%8F%E8%AE%AE/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title"></div>
    </a>
  
</nav>

  
</article>


</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Categories</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C#工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/C-%E5%B7%A5%E5%85%B7/">C++工具</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/Mysql/">Mysql</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/blender/">blender</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/linux/">linux</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/manim/">manim</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/spring/">spring</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C/">vba基础操作</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E5%88%9B%E9%80%A0%E6%A8%A1%E5%BC%8F/">创造模式</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/">操作系统</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">操作系统基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91/">操作系统开发</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E5%AD%A6/">数学</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/">数据结构基础知识</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%A8%A1%E6%9D%BF/">模板</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/">深度学习</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%8B%B1%E8%AF%AD/">英语</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%99%9A%E5%B9%BB4/">虚幻4</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86/">计算机组成原理</a></li><li class="category-list-item"><a class="category-list-link" href="/notes-on-computer-expertise/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/">计算机网络</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/notes-on-computer-expertise/tags/C/" rel="tag">C++</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/notes-on-computer-expertise/tags/C/" style="font-size: 10px;">C++</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/05/">May 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/03/">March 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/02/">February 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2022/01/">January 2022</a></li><li class="archive-list-item"><a class="archive-list-link" href="/notes-on-computer-expertise/archives/2021/12/">December 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/31/vue/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E9%AA%8C%E8%AF%81%E7%A0%81%E6%97%A0%E6%B3%95%E6%98%BE%E7%A4%BA/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/26/%E6%95%B0%E6%8D%AE%E5%BA%93/navicat%E5%AE%89%E8%A3%85/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/25/%E8%99%9A%E5%B9%BB4%E5%BC%95%E6%93%8E%E5%BC%80%E5%8F%91/%E8%99%9A%E5%B9%BB%E5%9B%9B%20mod%E5%88%B6%E4%BD%9C/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/python/python%E6%89%B9%E9%87%8F%E7%94%9F%E6%88%90%E6%95%B0%E6%8D%AE/">(no title)</a>
          </li>
        
          <li>
            <a href="/notes-on-computer-expertise/2022/05/23/vba%E5%9F%BA%E7%A1%80%E6%93%8D%E4%BD%9C%E7%AC%94%E8%AE%B0/EXCEL%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B/">(no title)</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2022 John Doe<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/notes-on-computer-expertise/" class="mobile-nav-link">Home</a>
  
    <a href="/notes-on-computer-expertise/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/notes-on-computer-expertise/js/jquery-3.4.1.min.js"></script>



  
<script src="/notes-on-computer-expertise/fancybox/jquery.fancybox.min.js"></script>




<script src="/notes-on-computer-expertise/js/script.js"></script>





  </div>
<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
        tex2jax: {
            inlineMath: [ ["$","$"], ["\\(","\\)"] ],
            skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'],
            processEscapes: true
        }
    });
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax();
        for (var i = 0; i < all.length; ++i)
            all[i].SourceElement().parentNode.className += ' has-jax';
    });
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
</body>
</html>